package qqhfpay

import (
	"bytes"
	"context"
	"encoding/json"
	"errors"
	url2 "net/url"

	"gitee.com/liuxuezhan/ar-platform/admin-api/internal/pay/base"
	"github.com/bytedance/sonic/decoder"
)

type Factory struct {
}

func (p *Factory) CreatePay(config base.Config) base.Payment {
	return &QQHPay{
		Url:        config.Url,
		SecretKey:  config.SecretKey,
		NotifyUrl:  config.NotifyUrl,
		MerchantId: config.MerchantId,
	}
}

type QQHPay struct {
	Url        string
	SecretKey  string
	NotifyUrl  string
	MerchantId string
}

type QQHResponse struct {
	Code string `json:"code"`
	Msg  string `json:"msg"`
	Data struct {
		SysOrderId string `json:"sysOrderId"` // 通道订单号
		Status     string `json:"status"`     // 交易状态（SUCCESS,NOTPAY-表示成功，其他都是失败，FAIL-失败，CLOSED-关闭）
		Amount     string `json:"amount"`     // 请求收款金额，金额 * 100
		Fee        string `json:"fee"`        // 手续费，金额 * 100
		RealAmount string `json:"realAmount"` // 实际到账金额，代码，金额 * 100
	} `json:"data"`

	Error string `json:"error"`
}

type QQHBalanceResponse struct {
	Code string `json:"code"`
	Msg  string `json:"msg"`
	Data struct {
		Balance float64 `json:"balance"`
	} `json:"data"`

	Error string `json:"error"`
}
type BalanceResp struct {
	Currency    string  `json:"currency"`    // 币种
	PayoutValue float64 `json:"payoutValue"` // 代付余额
}

// Withdraw QQHPay代付订单创建
func (qqh *QQHPay) Withdraw(ctx context.Context, req map[string]any) (resp base.WithdrawRes, err error) {
	params := make(map[string]any)

	// 第三方必传参数
	params["merchantNo"] = qqh.MerchantId
	params["version"] = "1.0"
	params["merchantOrderId"] = req["Order"].(map[string]any)["OrderNo"]
	params["channelCode"] = "NGASVIPFF"

	params["amount"] = int(req["Order"].(map[string]any)["Amount"].(float64)) // float64
	params["currency"] = "NGN"
	params["userName"] = req["Order"].(map[string]any)["UserBank"].(map[string]any)["UserName"].(string)
	if params["userName"] == "" {
		err = errors.New("userName is required")
		return
	}
	params["expireTime"] = 60
	// 验证bankInfo
	bankCode := req["Order"].(map[string]any)["UserBank"].(map[string]any)["BankCode"].(string)
	if bankCode == "" {
		err = errors.New("invalid bankCode params")
		return
	}
	bankAccount := req["Order"].(map[string]any)["UserBank"].(map[string]any)["CardNumber"].(string)
	if bankAccount == "" {
		err = errors.New("invalid bankAccount params")
		return
	}
	var buf bytes.Buffer
	err = json.NewEncoder(&buf).Encode(map[string]string{
		"bankCode":   bankCode,
		"cardNumber": bankAccount,
	})
	if err != nil {
		return base.WithdrawRes{}, err
	}
	params["bankInfo"] = buf.String()

	// 第三方可选参数
	params["notifyUrl"] = qqh.NotifyUrl
	_, ok := req["UserRemark"]
	if ok {
		params["remark"] = req["UserRemark"]
	}
	_, ok = req["extInfo"] // 格式为JSON字符串
	if ok {
		params["extInfo"] = req["extInfo"]
	}
	_email := req["Order"].(map[string]any)["UserBank"].(map[string]any)["Email"].(string)
	if _email != "" {
		params["email"] = _email
	} else {
		// todo
		params["email"] = "zhangsan@coolgame.world"
	}
	_mobileNo := req["Order"].(map[string]any)["UserBank"].(map[string]any)["Phone"].(string)
	if _mobileNo != "" {
		params["mobileNo"] = _mobileNo
	} else {
		// todo
		params["mobileNo"] = "15512345678"
	}

	// 生成签名
	params["sign"], err = GenerateSignatureOfQqhf(params, qqh.SecretKey)
	if err != nil {
		return
	}

	// 请求第三方接口

	url, _ := url2.JoinPath(qqh.Url, "/payout/unifiedorder.do")
	_, err = sendRequest(ctx, url, params, "post")
	if err != nil {
		return
	}
	resp = base.WithdrawRes{
		OrderSn: req["Order"].(map[string]any)["OrderNo"].(string),
		// ThirdOrderSn: result.Data.SysOrderId,
	}
	return
}

// 余额查询
func (qqh *QQHPay) Balance(ctx context.Context) (BalanceResp, error) {
	// 请求第三方接口
	url := qqh.Url + "/balance/query.do"
	params := make(map[string]any)
	params["merchantNo"] = qqh.MerchantId
	params["version"] = "1.0"
	params["balanceType"] = "OUT" // 余额类型（IN/OUT），IN-收款余额，OUT-代付备付金
	params["currency"] = "NGN"
	sign, err := GenerateSignatureOfQqhf(params, qqh.SecretKey)
	if err != nil {
		return BalanceResp{}, err
	}
	params["sign"] = sign

	result, err := sendBalanceRequest(ctx, url, params, "get")
	if err != nil {
		return BalanceResp{}, err
	}
	return BalanceResp{
		Currency:    "NGN",
		PayoutValue: result.Data.Balance,
	}, nil
}

// 发送请求
func sendRequest(ctx context.Context, url string, params map[string]any, method string) (resp QQHResponse, err error) {
	output, err := base.SendJson(ctx, url, params, method)
	if err != nil {
		return resp, err
	}
	dc := decoder.NewDecoder(output)
	dc.UseNumber()
	dc.Decode(&resp)

	var errMsg string
	if resp.Error != "" {
		errMsg = resp.Error
	} else if resp.Msg != "" {
		errMsg = resp.Msg
	} else {
		errMsg = resp.Code
	}

	if resp.Code != "000" {
		return resp, errors.New(errMsg)
	}
	if resp.Data.Status != "SUCCESS" && resp.Data.Status != "NOTPAY" {
		return resp, errors.New(errMsg)
	}
	return
}

func sendBalanceRequest(ctx context.Context, url string, params map[string]any, method string) (resp QQHBalanceResponse, err error) {
	output, err := base.SendJson(ctx, url, params, method)
	if err != nil {
		return resp, err
	}
	dc := decoder.NewDecoder(output)
	dc.UseNumber()
	dc.Decode(&resp)
	if resp.Code != "SUCCESS" && resp.Code != "NOTPAY" {
		return resp, errors.New(resp.Error)
	}
	return
}
